﻿using HandyControl.Controls;
using HandyControl.Tools;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Media;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using static SystemBackdropTypes.PInvoke.Methods;
using static SystemBackdropTypes.PInvoke.ParameterTypes;
using Brush = System.Windows.Media.Brush;
using File = System.IO.File;

namespace EzyConfigurator
{
    /// <summary>
    /// ConfiguratorMain.xaml 的交互逻辑
    /// </summary>
    /// 
    #region Acrylic Stuff
    internal enum AccentState
    {
        ACCENT_DISABLED = 0,
        ACCENT_ENABLE_GRADIENT = 1,
        ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
        ACCENT_ENABLE_BLURBEHIND = 3,
        ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
        ACCENT_INVALID_STATE = 5
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct AccentPolicy
    {
        public AccentState AccentState;
        public uint AccentFlags;
        public uint GradientColor;
        public uint AnimationId;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct WindowCompositionAttributeData
    {
        public WindowCompositionAttribute Attribute;
        public IntPtr Data;
        public int SizeOfData;
    }

    internal enum WindowCompositionAttribute
    {
        // ...
        WCA_ACCENT_POLICY = 19
        // ...
    }
    #endregion

    public partial class ConfiguratorMain : System.Windows.Window, INotifyPropertyChanged
    {

        #region Also Acrylic stuff
        [DllImport("user32.dll")]
        internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);

        private uint _blurOpacity;
        public double BlurOpacity
        {
            get { return _blurOpacity; }
            set { _blurOpacity = (uint)value; EnableBlur(); }
        }

        private uint _blurBackgroundColor = 0xFFFFFF; /* BGR color format */
        #endregion


        internal void EnableBlur()
        {
            BrushConverter bc = new BrushConverter();
            MainGrid.Background = (Brush)bc.ConvertFromString("#CCFFFFFF");

            var windowHelper = new WindowInteropHelper(this);
            var accent = new AccentPolicy();
            accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND;
            accent.GradientColor = (_blurOpacity << 24) | (_blurBackgroundColor & 0xFFFFFF);

            var accentStructSize = Marshal.SizeOf(accent);

            var accentPtr = Marshal.AllocHGlobal(accentStructSize);
            Marshal.StructureToPtr(accent, accentPtr, false);

            var data = new WindowCompositionAttributeData();
            data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY;
            data.SizeOfData = accentStructSize;
            data.Data = accentPtr;

            SetWindowCompositionAttribute(windowHelper.Handle, ref data);

            Marshal.FreeHGlobal(accentPtr);
        }

        Version[] mainVersions = new Version[6];
        Version[] installerVersions = new Version[6];
        string[] installerUrls = new string[]{
            "http://djdjz7.gitee.io/zyflier/update/installer.exe",
            "http://legacy.openflier.top/update/installer.exe",
            "http://djdjz7.github.io/zyflier/update/installer.exe",
            "https://github.com/djdjz7/zyflier/blob/main/update/installer.exe",
            "https://cdn.jsdelivr.net/gh/djdjz7/zyflier/update/installer.exe",
        };


        public ConfiguratorMain()
        {
            InitializeComponent();
            DataContext = this;
        }
        void OnLoaded(object sender, RoutedEventArgs e)
        {
            try
            {
                Version currentVersion = Environment.OSVersion.Version;
                Version Windows7 = new Version("6.1");
                Version SupportedWindows11 = new Version("10.0.22523");
                Version BaseWindows11 = new Version("10.0.22000");
                Version SupportedWindows10 = new Version("10.0.17134");
                if (currentVersion.CompareTo(SupportedWindows11) >= 0 || (currentVersion.Major == 6 && currentVersion.Minor == 1))
                {
                    RefreshFrame();
                    RefreshDarkMode();
                    SetWindowAttribute(
                        new WindowInteropHelper(this).Handle,
                        DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE,
                        4);
                }
                else if (currentVersion.CompareTo(SupportedWindows10) >= 0 && currentVersion.CompareTo(BaseWindows11) < 0)
                {
                    BlurOpacity = 0;
                    EnableBlur();
                }
                else
                {
                    BrushConverter brushConverter = new BrushConverter();
                    this.Background = (Brush)brushConverter.ConvertFromString("#FFEEEEEE");
                }
            }
            catch { }
            finally
            {
                if (!File.Exists("config.ini"))
                    File.Create("config.ini").Close();
                LoadIniFile(Environment.CurrentDirectory + "\\config.ini");
                RestoreIniStatus.Text = "";
                ListBoxMain.SelectedIndex = 1;
                PopUp.Visibility = Visibility.Hidden;

                Thread UpdateSourceCheckThread = new Thread(UpdateSourceCheck);
                UpdateSourceCheckThread.Start();
                Thread FakeVerNewestCheckThread = new Thread(FakeVerNewestCheck);
                FakeVerNewestCheckThread.Start();

                FileVersionInfo fi = FileVersionInfo.GetVersionInfo(Environment.CurrentDirectory + "\\" + Process.GetCurrentProcess().ProcessName + ".exe");
                ConfiguratorVerText.Text = fi.FileVersion;
            }
        }
        public class VersionCheckReturnValue
        {
            public VersionCheckReturnValueData data;
            public string code;
            public string msg;
        }
        public class VersionCheckReturnValueData
        {
            public string schoolCode;
            public string versionId;
            public string versionName;
            public string packageUrl;
        }
        private void FakeVerNewestCheck()
        {
            try
            {
                HttpClient client = new HttpClient();
                client.Timeout = TimeSpan.FromSeconds(5);
                string rawData = client.GetStringAsync("http://note.func.zykj.org/api/account/GetVersion").Result;
                VersionCheckReturnValue returnValue = JsonConvert.DeserializeObject<VersionCheckReturnValue>(rawData);
                if (returnValue.msg == "操作成功")
                {
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        FakeVerNewest.Text = "从中育服务器上获得的最新版本：" + returnValue.data.versionName;
                    });
                }
                else
                {
                    Exception exception = new Exception("返回值未表明成功");
                    throw exception;
                }
            }
            catch (Exception ex)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    FakeVerNewest.Text = "无法从中育服务器上获得的最新版本：" + ex.Message;
                });
            }
        }
        private void UpdateSourceCheck()
        {

            Application.Current.Dispatcher.Invoke(() =>
            {
                try
                {
                    FileVersionInfo fi = FileVersionInfo.GetVersionInfo(Environment.CurrentDirectory + "\\CloudRoom.Main.exe");
                    mainVersions[0] = Version.Parse(fi.FileVersion);
                    LocalVerText.Text = "本地版本：" + fi.FileVersion + "/";
                }
                catch (Exception ex)
                {
                    LocalVerText.Text = "本地版本：错误" + ex.Message + "/";
                    mainVersions[0] = new Version("0.0");
                }
                try
                {
                    FileVersionInfo localInstallerVerInfo = FileVersionInfo.GetVersionInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\中育飞车助手\\Installer.exe");
                    installerVersions[0] = Version.Parse(localInstallerVerInfo.FileVersion);
                    LocalVerText.Text += installerVersions[0];
                }
                catch (Exception ex)
                {
                    installerVersions[0] = new Version("0.0");
                    LocalVerText.Text += "错误：" + ex.Message;
                }
            });



            Application.Current.Dispatcher.Invoke(() =>
            {
                GiteeVerText.Text = "Gitee 版本：正在检查...";
                CloudflareVerText.Text = "openflier.top 版本：正在检查...";
                GithubVerText.Text = "Github 版本：正在检查...";
                ghproxyVerText.Text = "Github (ghproxy) 版本：正在检查...";
                JsdelivrVerText.Text = "JSDELIVR 版本：正在检查...";
                StartUpdateSource.IsEnabled = false;
                StartUpdateButton.IsEnabled = false;
                RefreshUpdateSource.IsEnabled = false;
            });

            HttpClient client = new HttpClient();
            client.Timeout = TimeSpan.FromSeconds(15);
            try
            {
                string giteever = client.GetStringAsync("http://djdjz7.gitee.io/zyflier/update/mainver").Result;
                string giteeInstallerver = client.GetStringAsync("http://djdjz7.gitee.io/zyflier/update/installerver").Result;
                mainVersions[1] = Version.Parse(giteever);
                installerVersions[1] = Version.Parse(giteeInstallerver);
                Application.Current.Dispatcher.Invoke(() =>
                {
                    GiteeVerText.Text = "Gitee 版本：" + giteever + "/" + installerVersions[1];
                    GiteeCBI.IsEnabled = true;

                });
            }
            catch (Exception e)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    GiteeVerText.Text = "Gitee 版本检查出错：" + e.Message;
                    StartUpdateSource.SelectedIndex = -1;
                    GiteeCBI.IsEnabled = false;
                    mainVersions[1] = new Version("0.0");
                    installerVersions[1] = new Version("0.0");
                });
            }

            try
            {
                string Cloudflarever = client.GetStringAsync("http://legacy.openflier.top/update/mainver").Result;
                string cloudflareInstallerver = client.GetStringAsync("http://legacy.openflier.top/update/installerver").Result;
                installerVersions[2] = Version.Parse(cloudflareInstallerver);
                mainVersions[2] = Version.Parse(Cloudflarever);
                Application.Current.Dispatcher.Invoke(() =>
                {
                    CloudflareVerText.Text = "openflier.top 版本：" + Cloudflarever + "/" + installerVersions[2];
                    CloudflareCBI.IsEnabled = true;

                });
            }
            catch (Exception e)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    CloudflareVerText.Text = "openflier.top 版本检查出错：" + e.Message;
                    CloudflareCBI.IsEnabled = false;
                    mainVersions[2] = new Version("0.0");
                    installerVersions[2] = new Version("0.0");
                });
            }

            try
            {
                string githubver = client.GetStringAsync("http://djdjz7.github.io/zyflier/update/mainver").Result;
                string githubInstallerVer = client.GetStringAsync("http://djdjz7.github.io/zyflier/update/installerver").Result;
                mainVersions[3] = Version.Parse(githubver);
                installerVersions[3] = Version.Parse(githubInstallerVer);
                Application.Current.Dispatcher.Invoke(() =>
                {
                    GithubVerText.Text = "Github 版本：" + githubver + "/" + installerVersions[3];
                    GithubCBI.IsEnabled = true;
                });
            }
            catch (Exception e)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    GithubVerText.Text = "Github 版本检查出错：" + e.Message;
                    GithubCBI.IsEnabled = false;
                    mainVersions[3] = new Version("0.0");
                    installerVersions[3] = new Version("0.0");
                });
            }

            try
            {
                string githubver = client.GetStringAsync("http://djdjz7.github.io/zyflier/update/mainver").Result;
                string githubInstallerVer = client.GetStringAsync("http://djdjz7.github.io/zyflier/update/installerver").Result;
                mainVersions[4] = Version.Parse(githubver);
                installerVersions[4] = Version.Parse(githubInstallerVer);
                Application.Current.Dispatcher.Invoke(() =>
                {
                    ghproxyVerText.Text = "Github (ghproxy) 版本：" + githubver + "/" + installerVersions[3];
                    ghproxyCBI.IsEnabled = true;
                });
            }
            catch (Exception e)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    ghproxyVerText.Text = "Github (ghproxy) 版本检查出错：" + e.Message;
                    ghproxyCBI.IsEnabled = false;
                    mainVersions[4] = new Version("0.0");
                    installerVersions[4] = new Version("0.0");
                });
            }

            try
            {
                string Jsdelivrver = client.GetStringAsync("https://cdn.jsdelivr.net/gh/djdjz7/zyflier/update/mainver").Result;
                string jsdelivrInstallerVer = client.GetStringAsync("https://cdn.jsdelivr.net/gh/djdjz7/zyflier/update/installerver").Result;
                mainVersions[5] = Version.Parse(Jsdelivrver);
                installerVersions[5] = Version.Parse(jsdelivrInstallerVer);
                Application.Current.Dispatcher.Invoke(() =>
                {
                    JsdelivrVerText.Text = "JSDELIVR 版本：" + Jsdelivrver + "/" + installerVersions[4];
                    JsdelivrCBI.IsEnabled = true;
                });
            }
            catch (Exception e)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    JsdelivrVerText.Text = "JSDELIVR 版本检查出错：" + e.Message;
                    JsdelivrCBI.IsEnabled = false;
                    mainVersions[5] = new Version("0.0");
                    installerVersions[5] = new Version("0.0");
                });
            }


            Application.Current.Dispatcher.Invoke(() =>
            {

                if (GiteeCBI.IsEnabled)
                    StartUpdateSource.SelectedIndex = 0;
                else if (CloudflareCBI.IsEnabled)
                    StartUpdateSource.SelectedIndex = 1;
                else if (GithubCBI.IsEnabled)
                    StartUpdateSource.SelectedIndex = 2;
                else if (ghproxyCBI.IsEnabled)
                    StartUpdateSource.SelectedIndex = 3;
                else if (JsdelivrCBI.IsEnabled)
                    StartUpdateSource.SelectedIndex = 4;
                else
                    StartUpdateSource.SelectedIndex = -1;

                StartUpdateSource.IsEnabled = true;
                StartUpdateButton.IsEnabled = true;
                RefreshUpdateSource.IsEnabled = true;
                if (!GiteeCBI.IsEnabled && !CloudflareCBI.IsEnabled && !GithubCBI.IsEnabled && !ghproxyCBI.IsEnabled && !JsdelivrCBI.IsEnabled)
                    StartUpdateButton.IsEnabled = false;
            });



        }
        private void RefreshFrame()
        {
            IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
            HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
            mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);

            MARGINS margins = new MARGINS();
            margins.cxLeftWidth = -1;
            margins.cxRightWidth = -1;
            margins.cyTopHeight = -1;
            margins.cyBottomHeight = -1;

            ExtendFrame(mainWindowSrc.Handle, margins);
        }
        private void RefreshDarkMode()
        {
            SetWindowAttribute(
                new WindowInteropHelper(this).Handle,
                DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE,
                0);
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            EnableBlur();
        }

        public static string RemoteRanSourceStr;

        public event PropertyChangedEventHandler? PropertyChanged;
        public void RaisePropertyChanged([CallerMemberName] string? propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private ObservableCollection<CommandInputSource> _commandInputSource = new ObservableCollection<CommandInputSource>();
        public ObservableCollection<CommandInputSource> CommandInputSource
        {
            get { return _commandInputSource; }
            set
            {
                _commandInputSource = value;
                RaisePropertyChanged();
            }
        }

        private void PrimaryColorPickButton_Click(object sender, RoutedEventArgs e)
        {
            var picker = SingleOpenHelper.CreateControl<HandyControl.Controls.ColorPicker>();
            var window = new PopupWindow
            {
                PopupElement = picker
            };
            picker.Loaded += delegate
            {
                picker.SelectedBrush = (SolidColorBrush)PrimaryColorPreview.Fill;
            };
            picker.Canceled += delegate
            { window.Close(); };
            picker.Confirmed += delegate
            {
                PrimaryColorPreview.Fill = picker.SelectedBrush;
                window.Close();
            };
            window.ShowDialog(PrimaryColorPreview, false);
        }

        private void SecondaryColorPickButton_Click(object sender, RoutedEventArgs e)
        {
            var picker = SingleOpenHelper.CreateControl<HandyControl.Controls.ColorPicker>();
            var window = new PopupWindow
            {
                PopupElement = picker
            };
            picker.Loaded += delegate
            {
                picker.SelectedBrush = (SolidColorBrush)SecondaryColorPreview.Fill;
            };
            picker.Canceled += delegate
            { window.Close(); };
            picker.Confirmed += delegate
            {
                SecondaryColorPreview.Fill = picker.SelectedBrush;
                window.Close();
            };
            window.ShowDialog(SecondaryColorPreview, false);
        }


        private void BackgroundBrowseButton_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
            ofd.Reset();
            ofd.Filter = "背景图片(*.bmp;*.jpg;*.jpeg;*.png)|*.bmp;*.jpg;*.jpeg;*.png";
            ofd.Multiselect = true;
            ofd.CheckFileExists = true;
            if ((bool)ofd.ShowDialog())
            {
                BackgroundImageSource.Text = string.Join('|', ofd.FileNames);
            }

        }

        private void GUIApply_Confirmed(object sender, RoutedEventArgs e)
        {
            PopUpPrimaryButton.Click -= GUIApply_Confirmed;
            IniWrite("Background", BackgroundImageSource.Text);
            IniWrite("ConnectCode", ConnectCodeTextBox.Text);
            IniWrite("TitleText", TitleTextTextBox.Text);
            if (AddCircleChkBox.IsChecked != null)
            {
                if ((bool)AddCircleChkBox.IsChecked)
                    IniWrite("AddCircle", "Yes");
                else
                    IniWrite("AddCircle", "No");
            }
            else
                IniWrite("AddCircle", "No");

            IniWrite("PrimaryColor", PrimaryColorPreview.Fill.ToString());
            IniWrite("SecondaryColor", SecondaryColorPreview.Fill.ToString());
            if (UsePNGChkBox.IsChecked != null)
            {
                if ((bool)UsePNGChkBox.IsChecked)
                    IniWrite("UsePNG", "Yes");
                else
                    IniWrite("UsePNG", "No");
            }
            else
                IniWrite("UsePNG", "No");
            //NO IMAGE TRANSFER HERE;

            IniWrite("LocalRanAllowedUser", LocalRanAllowedUser.Text);
            IniWrite("LocalRanSource", LocalRanSource.Text);
            IniWrite("RemoteRanAllowedUser", RemoteRanAllowedUser.Text);
            IniWrite("RemoteRanSource", RemoteRanSource.Text);
            IniWrite("WebshotAllowedUser", WebshotAllowedUser.Text);
            IniWrite("WebshotSource", WebshotSource.Text);
            IniWrite("CMDAllowedUser", CMDAllowedUser.Text);
            IniWrite("FakeVersion", FakeVersionTextBox.Text);
            /*
            AskRestart ar = new AskRestart();
            ar.ShowDialog();
            PopUpFadeOut();*/
            ShowWarning("某些设置项可能需要重新启动程序以应用更改，这些设置项包括：\n背景图片 窗口标题 连接密码及其属性 颜色 SpecialChannels用户\n若以上设置发生更改，请重新启动应用程序，否则可以保持程序继续运行。",
                "更改完成",
                "立即重新启动", "取消", "\ue7ba", "#FFFFC200", RestartApplication, SystemSounds.Exclamation, true);
            File.WriteAllText("cmdsource.json", JsonConvert.SerializeObject(CommandInputSource));
            LoadIniFile(Environment.CurrentDirectory + "\\config.ini");
        }

        private void RestartApplication(object sender, RoutedEventArgs e)
        {
            PopUpPrimaryButton.Click -= RestartApplication;
            Process[] processes = Process.GetProcesses();
            foreach (var p in processes)
            {
                if (p.ProcessName == "CloudRoom.Main")
                    p.Kill();
            }
            try
            {
                Process.Start("CloudRoom.Main.exe");
                PopUpFadeOut();
            }
            catch (Exception ex)
            {
                ShowWarning("程序启动失败\n" + ex.Message, "错误", null, "忽略", "\uea39", "Red", null, SystemSounds.Hand, true);
                //MessageBox.Show("程序启动失败\n" + ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }

        }

        private void GUIApply_Click(object sender, RoutedEventArgs e)
        {
            if (Regex.IsMatch(ConnectCodeTextBox.Text, @"^\d{4}$") || string.IsNullOrEmpty(ConnectCodeTextBox.Text))
            {
                ShowWarning("将覆盖原有配置，继续？", "警告", "继续", "取消", "\ue7ba", "#FFFFC200",
                    GUIApply_Confirmed,
                    SystemSounds.Exclamation, false);

            }
            else
                ShowWarning("连接密码格式不正确\n连接密码应为四位数字，或留空以使用默认配置", "错误", "", "好", "\uea39", "Red", null, SystemSounds.Hand, false);


        }

        private void SourceApply_Click(object sender, RoutedEventArgs e)
        {
            ShowWarning("注意：应用源将不会对其进行可用性检查。将覆盖原有配置，继续？", "警告", "继续", "取消", "\ue7ba", "#FFFFC200",
                    SourceApply_Confirmed,
                    SystemSounds.Exclamation, false);
        }

        private void SourceApply_Confirmed(object sender, RoutedEventArgs e)
        {
            PopUpPrimaryButton.Click -= SourceApply_Confirmed;
            File.WriteAllText(Environment.CurrentDirectory + "\\config.ini", IniSourceTextBox.Text);

            ShowWarning("某些设置项可能需要重新启动程序以应用更改，这些设置项包括：\n背景图片 窗口标题 连接密码及其属性 颜色 SpecialChannels用户\n若以上设置发生更改，请重新启动应用程序，否则可以保持程序继续运行。",
                "更改完成",
                "立即重新启动", "取消", "\ue7ba", "#FFFFC200", RestartApplication, SystemSounds.Exclamation, true);
            LoadIniFile(Environment.CurrentDirectory + "\\config.ini");
        }

        private void IniWrite(string key, string value)
        {
            Ini.Write("Mod", key, value, Environment.CurrentDirectory + "\\config.ini");
        }

        private string IniRead(string key, string path)
        {
            return Ini.Read("Mod", key, "", path);
        }
        private void LoadIniFile(string filename)
        {
            BrushConverter bc = new BrushConverter();
            string temp;
            BackgroundImageSource.Text = IniRead("Background", filename);
            ConnectCodeTextBox.Text = IniRead("ConnectCode", filename);
            if (IniRead("AddCircle", filename) == "Yes")
                AddCircleChkBox.IsChecked = true;
            if (IniRead("UsePNG", filename) == "Yes")
                UsePNGChkBox.IsChecked = true;
            temp = IniRead("TitleText", filename);
            if (string.IsNullOrEmpty(temp))
                temp = "中育课堂助手";
            TitleTextTextBox.Text = temp;

            temp = IniRead("FakeVersion", filename);
            if (string.IsNullOrEmpty(temp))
                temp = "2.1.0";
            FakeVersionTextBox.Text = temp;

            temp = IniRead("PrimaryColor", filename);
            if (!TryColorConvert(temp))
                temp = "White";
            PrimaryColorPreview.Fill = (Brush)bc.ConvertFromString(temp);
            temp = IniRead("SecondaryColor", filename);
            if (!TryColorConvert(temp))
                temp = "DarkGray";
            SecondaryColorPreview.Fill = (Brush)bc.ConvertFromString(temp);
            LocalRanSource.Text = IniRead("LocalRanSource", filename);
            LocalRanAllowedUser.Text = IniRead("LocalRanAllowedUser", filename);
            temp = IniRead("RemoteRanSource", filename);
            if (string.IsNullOrEmpty(temp))
                temp = "https://img.paulzzh.tech/touhou/random";
            RemoteRanSource.Text = temp;
            RemoteRanAllowedUser.Text = IniRead("RemoteRanAllowedUser", filename);
            WebshotSource.Text = IniRead("WebshotSource", filename);
            WebshotAllowedUser.Text = IniRead("WebshotAllowedUser", filename);
            CMDAllowedUser.Text = IniRead("CMDAllowedUser", filename);
            TransferImageSource.Text = IniRead("TransferImage", filename);

            UsePNGChkBox.IsChecked = false;
            AddCircleChkBox.IsChecked = false;
            if (IniRead("UsePNG", filename) == "Yes")
                UsePNGChkBox.IsChecked = true;
            if (IniRead("AddCircle", filename) == "Yes")
                AddCircleChkBox.IsChecked = true;
            IniSourceTextBox.Text = File.ReadAllText(filename);
            if(File.Exists("cmdsource.json"))
            {
                var cmdSourceContent = File.ReadAllText("cmdsource.json");
                var sourceList = JsonConvert.DeserializeObject<List<CommandInputSource>>(cmdSourceContent);
                CommandInputSource = new ObservableCollection<CommandInputSource>(sourceList);
            }    
            ImportIniStatus.Text = "配置文件已加载：" + filename;
        }

        private bool TryColorConvert(string colorcode)
        {
            try
            {
                BrushConverter bc = new BrushConverter();
                bc.ConvertFromString(colorcode);
                return true;
            }
            catch
            {
                return false;
            }
        }

        private void ImportIniButton_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
            ofd.Reset();
            ofd.Filter = "配置文件(*.ini)|*.ini";
            ofd.Multiselect = false;
            ofd.CheckFileExists = false;
            if ((bool)ofd.ShowDialog())
                LoadIniFile(ofd.FileName);

        }

        private void WebshotAllowAllButton_Click(object sender, RoutedEventArgs e)
        {
            WebshotAllowedUser.Text = "Everyone";
        }

        private void RemoteRanAllowAllButton_Click(object sender, RoutedEventArgs e)
        {
            RemoteRanAllowedUser.Text = "Everyone";
        }

        private void LocalRanAllowAllButton_Click(object sender, RoutedEventArgs e)
        {
            LocalRanAllowedUser.Text = "Everyone";
        }

        private void TransferImageBrowseButton_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
            ofd.Reset();
            ofd.Filter = "传输图片(*.bmp;*.jpg;*.jpeg;*.png;*.webp)|*.bmp;*.jpg;*.jpeg;*.png;*.webp";
            ofd.Multiselect = false;
            ofd.CheckFileExists = true;
            if ((bool)ofd.ShowDialog())
                TransferImageSource.Text = ofd.FileName;
        }

        private void RestoreToDefaultButton_Click(object sender, RoutedEventArgs e)
        {
            File.WriteAllText("config.ini", "");
            ShowWarning("重新启动应用程序以应用更改",
                "已恢复",
                "立即重新启动", "", "\ue7ba", "#FFFFC200", RestartApplication, SystemSounds.Exclamation, false);

            LoadIniFile(Environment.CurrentDirectory + "\\config.ini");
        }

        private void TransferImageApplyButton_Click(object sender, RoutedEventArgs e)
        {
            IniWrite("TransferImage", TransferImageSource.Text);

        }

        private void TransferImageResetButton_Click(object sender, RoutedEventArgs e)
        {
            IniWrite("TransferImage", "");
            TransferImageSource.Text = "";
        }

        private void LocalRanSourceBrowseButton_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
            ofd.Reset();
            ofd.Filter = "图片(*.bmp;*.jpg;*.jpeg;*.png;*.webp)|*.bmp;*.jpg;*.jpeg;*.png;*.webp";
            ofd.Multiselect = true;
            ofd.CheckFileExists = true;
            if ((bool)ofd.ShowDialog())
                LocalRanSource.Text = String.Join('|', ofd.FileNames);
        }

        private void DragIniArea_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {

                string temp = ((string[])e.Data.GetData(DataFormats.FileDrop))[0];
                if (temp.EndsWith(".ini", StringComparison.OrdinalIgnoreCase))
                {
                    LoadIniFile(temp);
                }
                else
                {
                    BrushConverter bc = new BrushConverter();
                    ImportIniStatus.Text = "× 不是有效的配置文件";
                    ImportIniStatus.Foreground = (Brush)bc.ConvertFromString("Red");
                }
            }
        }

        private void DragIniArea_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effects = DragDropEffects.Link;
            }
            else
            {
                e.Effects = DragDropEffects.None;
            }
        }

        private void BackgroundSourceTextBox_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effects = DragDropEffects.Link;
            }
            else
            {
                e.Effects = DragDropEffects.None;
            }
        }

        private void BackgroundSourceTextBox_Drop(object sender, DragEventArgs e)
        {
            string[] temp = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (CheckFormat(temp, false))
                BackgroundImageSource.Text = string.Join('|', temp);
            else
                ShowWarning("至少存在一项不是图片", "错误", "", "关闭", "\uea39", "Red", null, SystemSounds.Hand, false);
            //System.Windows.MessageBox.Show("至少存在一项不是图片", "错误", MessageBoxButton.OK, MessageBoxImage.Error);

        }

        private void TransferImageSource_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effects = DragDropEffects.Link;
            }
            else
            {
                e.Effects = DragDropEffects.None;
            }
        }

        private void TransferImageSource_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] temp = { ((string[])e.Data.GetData(DataFormats.FileDrop))[0] };
                if (CheckFormat(temp, true))
                    TransferImageSource.Text = string.Join('|', temp);
                else
                    ShowWarning("不是图片", "错误", "", "关闭", "\uea39", "Red", null, SystemSounds.Hand, false);
                //System.Windows.MessageBox.Show("不是图片", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void LocalRanSource_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effects = DragDropEffects.Link;
            }
            else
            {
                e.Effects = DragDropEffects.None;
            }
        }

        private void LocalRanSource_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] temp = (string[])e.Data.GetData(DataFormats.FileDrop);
                if (CheckFormat(temp, true))
                    LocalRanSource.Text = string.Join('|', temp);
                else
                    ShowWarning("至少存在一项不是图片", "错误", "", "关闭", "\uea39", "Red", null, SystemSounds.Hand, false);
                //System.Windows.MessageBox.Show("至少存在一项不是图片", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }


        private bool CheckFormat(string[] strings, bool allowWebp)
        {
            foreach (string s in strings)
            {
                if (allowWebp)
                {
                    if (!s.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) &&
                        !s.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) &&
                        !s.EndsWith(".png", StringComparison.OrdinalIgnoreCase) &&
                        !s.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) &&
                        !s.EndsWith(".webp", StringComparison.OrdinalIgnoreCase))
                        return false;
                }
                else
                {
                    if (!s.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) &&
                        !s.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) &&
                        !s.EndsWith(".png", StringComparison.OrdinalIgnoreCase) &&
                        !s.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase))
                        return false;
                }

            }
            return true;
        }

        private void ListBoxMain_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            switch (ListBoxMain.SelectedIndex)
            {
                case 0:
                    FileGrid.Visibility = Visibility.Visible;
                    BasicsGrid.Visibility = Visibility.Hidden;
                    SpecialChannelsGrid.Visibility = Visibility.Hidden;
                    IniSourceGrid.Visibility = Visibility.Hidden;
                    GUIApplyButton.Visibility = Visibility.Visible;
                    SourceApplyButton.Visibility = Visibility.Hidden;
                    AboutGrid.Visibility = Visibility.Hidden;
                    break;
                case 1:
                    FileGrid.Visibility = Visibility.Hidden;
                    BasicsGrid.Visibility = Visibility.Visible;
                    SpecialChannelsGrid.Visibility = Visibility.Hidden;
                    IniSourceGrid.Visibility = Visibility.Hidden;
                    GUIApplyButton.Visibility = Visibility.Visible;
                    SourceApplyButton.Visibility = Visibility.Hidden;
                    AboutGrid.Visibility = Visibility.Hidden;
                    break;
                case 2:
                    FileGrid.Visibility = Visibility.Hidden;
                    BasicsGrid.Visibility = Visibility.Hidden;
                    SpecialChannelsGrid.Visibility = Visibility.Visible;
                    IniSourceGrid.Visibility = Visibility.Hidden;
                    GUIApplyButton.Visibility = Visibility.Visible;
                    SourceApplyButton.Visibility = Visibility.Hidden;
                    AboutGrid.Visibility = Visibility.Hidden;
                    break;
                case 3:
                    FileGrid.Visibility = Visibility.Hidden;
                    BasicsGrid.Visibility = Visibility.Hidden;
                    SpecialChannelsGrid.Visibility = Visibility.Hidden;
                    IniSourceGrid.Visibility = Visibility.Visible;
                    GUIApplyButton.Visibility = Visibility.Hidden;
                    SourceApplyButton.Visibility = Visibility.Visible;
                    AboutGrid.Visibility = Visibility.Hidden;
                    break;
                case 4:
                    FileGrid.Visibility = Visibility.Hidden;
                    BasicsGrid.Visibility = Visibility.Hidden;
                    SpecialChannelsGrid.Visibility = Visibility.Hidden;
                    IniSourceGrid.Visibility = Visibility.Hidden;
                    GUIApplyButton.Visibility = Visibility.Hidden;
                    SourceApplyButton.Visibility = Visibility.Hidden;
                    AboutGrid.Visibility = Visibility.Visible;
                    break;
                default:
                    FileGrid.Visibility = Visibility.Hidden;
                    BasicsGrid.Visibility = Visibility.Visible;
                    SpecialChannelsGrid.Visibility = Visibility.Hidden;
                    IniSourceGrid.Visibility = Visibility.Hidden;
                    GUIApplyButton.Visibility = Visibility.Visible;
                    SourceApplyButton.Visibility = Visibility.Hidden;
                    AboutGrid.Visibility = Visibility.Hidden;
                    break;
            }
        }


        private void DispatcherShowWarning(string content, string caption, string PrimaryContent, string SecondaryContent, string Icon, string IconColor, RoutedEventHandler? PrimaryAction, System.Media.SystemSound Sound, bool IsHotPatch)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                ShowWarning(content, caption, PrimaryContent, SecondaryContent, Icon, IconColor, PrimaryAction, Sound, IsHotPatch);
            });
        }

        private void ShowWarning(string content, string caption, string PrimaryContent, string SecondaryContent, string Icon, string IconColor, RoutedEventHandler? PrimaryAction, System.Media.SystemSound Sound, bool IsHotPatch)
        {
            PopUpTitle.Text = caption;
            PopUpContent.Text = content;
            if (string.IsNullOrEmpty(PrimaryContent))
                PopUpPrimaryButton.Visibility = Visibility.Collapsed;
            else
            {
                PopUpPrimaryButton.Content = PrimaryContent;
                PopUpPrimaryButton.Visibility = Visibility.Visible;
            }
            if (string.IsNullOrEmpty(SecondaryContent))
                PopUpSecondaryButton.Visibility = Visibility.Collapsed;
            else
            {
                PopUpSecondaryButton.Content = SecondaryContent;
                PopUpSecondaryButton.Visibility = Visibility.Visible;
            }
            if (PrimaryAction != null)
            {
                PopUpPrimaryButton.Click += PrimaryAction;
                PopUpSecondaryButton.Click += (object sender, RoutedEventArgs e) =>
                {
                    PopUpPrimaryButton.Click -= PrimaryAction;
                };
            }

            PopUpIcon.Text = Icon;
            BrushConverter bc = new BrushConverter();
            PopUpIcon.Foreground = (Brush)bc.ConvertFromString(IconColor);
            Sound.Play();

            if (IsHotPatch)
                return;


            PopUp.Opacity = 0;
            PopUp.Visibility = Visibility.Visible;


            var scaleTransform = new ScaleTransform();
            PopUpWindow.RenderTransform = scaleTransform;
            PopUpWindow.RenderTransformOrigin = new System.Windows.Point(0.5, 0.5);
            var scaleAnimation = new DoubleAnimation
            {
                From = 1.03,
                To = 1,
                Duration = TimeSpan.FromSeconds(0.08),
                FillBehavior = FillBehavior.Stop,
                DecelerationRatio = 0.5,
                AccelerationRatio = 0.5,

            };
            scaleAnimation.Completed += delegate
            {
                scaleTransform.ScaleX = 1;
                scaleTransform.ScaleY = 1;
            };

            var fadeInAnimation = new DoubleAnimation
            {
                From = 0,
                To = 1,
                Duration = TimeSpan.FromSeconds(0.08),
                FillBehavior = FillBehavior.Stop,
                DecelerationRatio = 0.3
            };
            fadeInAnimation.Completed += delegate
                {
                    PopUp.Opacity = 1;
                    PopUp.Visibility = Visibility.Visible;
                };
            scaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
            scaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);
            PopUp.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation);


        }

        private void PopUpSecondaryButton_Click(object sender, RoutedEventArgs e)
        {
            PopUpFadeOut();
        }

        private void PopUpFadeOut()
        {
            var animation = new DoubleAnimation
            {
                From = 1,
                To = 0,
                Duration = TimeSpan.FromSeconds(0.08),
                FillBehavior = FillBehavior.Stop
            };
            animation.Completed += delegate
            {
                PopUp.Opacity = 0;
                PopUp.Visibility = Visibility.Hidden;
            };
            PopUp.BeginAnimation(UIElement.OpacityProperty, animation);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Thread UpdateSourceCheckThread = new Thread(UpdateSourceCheck);
            UpdateSourceCheckThread.Start();
        }

        private void StartUpdateButton_Click(object sender, RoutedEventArgs e)
        {
            Thread StartUpdateThread = new Thread(StartUpdateActions);
            StartUpdateThread.Start(StartUpdateSource.SelectedIndex);
            StartUpdateButton.IsEnabled = false;
            StartUpdateButton.Content = "正在更新安装器";
        }



        public void StartUpdateActions(object? obj)
        {
            try
            {
                int i = int.Parse(obj.ToString());
                if (installerVersions[i + 1].CompareTo(installerVersions[0]) > 0)
                {
                    if (i == 3)
                    {
                        DispatcherShowWarning("安装器不是最新，且不能从 JSDELIVR 更新安装器，请选择其他更新服务器", "错误", "", "好", "\uea39",
                            "Red", null, SystemSounds.Hand, false);
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            StartUpdateButton.Content = "启动更新";
                            StartUpdateButton.IsEnabled = true;
                        });
                        return;
                    }

                    try
                    {
                        HttpClient client = new HttpClient();
                        byte[] data = client.GetByteArrayAsync(installerUrls[i]).Result;
                        File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\中育飞车助手\\Installer.exe", data);
                    }
                    catch (Exception ex)
                    {
                        DispatcherShowWarning(ex.Message, "错误", "", "好", "\uea39",
                            "Red", null, SystemSounds.Hand, false);
                    }

                }
                Application.Current.Dispatcher.Invoke(() =>
                {
                    var process = new Process
                    {
                        StartInfo =
                    {
                        WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)+"\\中育飞车助手",
                        UseShellExecute = true,
                        FileName = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)+"\\中育飞车助手\\Installer.exe",
                        Arguments = "update " + StartUpdateSource.Text,
                        Verb = "runas"
                    }
                    };
                    process.Start();
                    Application.Current.Shutdown();
                });


            }
            catch (Exception ex)
            {
                DispatcherShowWarning(ex.Message, "错误", "", "关闭", "\uea39", "Red", null, SystemSounds.Hand, false);
            }
        }


        private void StartUpdateSource_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }


        protected override void OnClosing(CancelEventArgs e)
        {
            e.Cancel = true;
            Process p = Process.GetCurrentProcess();
            p.Kill();

        }

        private void CMDAllowAllButton_Click(object sender, RoutedEventArgs e)
        {
            CMDAllowedUser.Text = "Everyone";
        }

        private void RegisterCMDUserButton_Click(object sender, RoutedEventArgs e)
        {
            RegisterCMDUserWindow registerCMDUserWindow = new();
            registerCMDUserWindow.ShowDialog();
        }

        private void HelpLink_Click(object sender, RoutedEventArgs e)
        {
            Process.Start("explorer", "http://legacy.openflier.top/help.html");
        }

        private void BackgroundImageResetButton_Click(object sender, RoutedEventArgs e)
        {
            BackgroundImageSource.Text = "";
        }

        private void LocalRanSourceResetButton_Click(object sender, RoutedEventArgs e)
        {
            LocalRanSource.Text = "";
        }

        private void CommandInputSourceAddButton_Click(object sender, RoutedEventArgs e)
        {
            CommandInputSource.Add(new CommandInputSource());
        }

        private void CommandInputSourceRemoveButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedItem = AllCommandInputSources.SelectedItem as CommandInputSource;
            if (selectedItem is null)
                return;
            CommandInputSource.Remove(selectedItem);
        }
    }
    public class CommandInputSource
    {
        public string UserIdentifier { get; set; }
        public string SnapshotUrl { get; set; }
    }
}
